/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
/**
 * \file
 * \brief Example client for building MaCI Clients apps. (With TaskCtrl interface)
 * \author Antti Maula <antti.maula@tkk.fi>
 * \author Matthieu Myrsky <matthieu.myrsky@tkk.fi>
 *
 * $Id: TaskCtrlClientExample.cpp,v 1.9 2009-10-09 11:08:52 mmatusia Exp $
 *
 */
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string>
#include <curses.h>
#include "owndebug.h"
#include "ownutils.h"
#include "binbag.h"
#include "TaskCtrlClient.hpp"

//*****************************************************************************
// Include GIMI in proper way
#define GIMI_CLIENT_API (20000)
#include "gimi.h"
//*****************************************************************************
// Set initial verbosity level to 1
static int verbose = 1;
//*****************************************************************************
// Choose your namespace
using namespace MaCI;
using namespace MaCI::TaskCtrl;
//*****************************************************************************
// Running?
static volatile bool run = true;
static ownThreadHandle signalHandlerThread;
//*****************************************************************************
static std::string datasource;
static std::string datasourceMaCISL;
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************

static int SignalHandlerThread(void *)
{
  dPrint(8, "Signal handler thread (%ld) starting...", pthread_self());

  while (run) {
    // Now, wait for requested signals to arrive
    int sig;
    sigset_t mask;
    sigemptyset(&mask);
    sigaddset(&mask, SIGINT);
    sigaddset(&mask, SIGTERM);
    sigaddset(&mask, SIGPIPE);
    sigaddset(&mask, SIGHUP);
    sigwait(&mask, &sig);

    // Got signal, sigwait returned!
    dPrint(1,"Got Signal '%d' (%s)", sig, strsignal(sig));

    // What to do?
    switch(sig) {
    case SIGINT:
    case SIGTERM:
    case SIGPIPE:
    case SIGHUP:
      run = false;
      ownSleep_ms(1000);
      break;
      
    default:
      dPrint(1,"Unhandled signal! Ignore!");
      break;
    }
  }
  return 0;
}
//*****************************************************************************

static void InitSignalHandler(void)
{
  // Now; Set to BLOCK ALL SIGNALS
  sigset_t mask;
  sigemptyset(&mask);
  sigaddset(&mask, SIGINT);
  sigaddset(&mask, SIGTERM);
  sigaddset(&mask, SIGPIPE);
  sigaddset(&mask, SIGHUP);
  pthread_sigmask(SIG_BLOCK, &mask, NULL);
  
  // Start signal handler thread
  signalHandlerThread = ownThread_Create((void*)SignalHandlerThread, NULL);
}
//*****************************************************************************
//*****************************************************************************

/**
 * All MaCI modules should support these parameters with exactly these names
 * *** DO NOT CHANGE NOR DELETE ANY OF THEM ***
 * Howevery, feel free to add new parameters as you wish.
 */
static void showUsage()
{
  fprintf(stderr,"\n");
  fprintf(stderr,"Usage:\tTaskCtrlClientExample [OPTIONS]\n");
  fprintf(stderr,"  [-u addr]\t\t\tUse 'addr' as GIMnet AccessPoints address\n");
  fprintf(stderr,"  [-p port]\t\t\tUse 'port' as GIMnet AccessPoints port\n");
  fprintf(stderr,"  [-n name]\t\t\tUse 'name' as this nodes GIMnet name\n");
  fprintf(stderr,"  [-s name]\t\t\tSpecify the data source\n");
  fprintf(stderr,"  [-i]\t\t\tInteractive mode (curses UI)\n");
  fprintf(stderr,"  \t\t\t\tOR\n");
  fprintf(stderr,"  [-S name]\t\t\tSpecify the data source by MaCISL\n\n");
  
  fprintf(stderr,"  [-v]\t\t\t\tIncrease verbosity by 1\n");
  fprintf(stderr,"  [-q]\t\t\t\tQuiet mode\n");
  fprintf(stderr,"Example:./TaskCtrlClientExample -S trader1.MaCI_TaskCtrl.TaskCtrlTaskInput");
  fprintf(stderr, "\n\n");
}
//*****************************************************************************

static int dummyWatch(CTaskCtrlClient *dc)
{
  CTaskCtrlData dd;
  bool r;


  dPrint(ODTEST,"Terminating Watch loop, as there is yet nothing to watch for :)");
  return 0;
  while(run) {

    //    r = dc->GetTaskCtrlEvent(dd, &sequence, 5000);
    if (r) {
      dPrint(1,"Got event:");
      dd.Print(1);
    }
  }
  
  return 0;
}


/**
 * Simple user class for TaskCtrlClient
 * Handle status events here!
 * If you use common variables with the client example main, use Mutexes
 * or suffer.
 */
class CTaskCtrlUser : public CTaskCtrlClientCallback
{    
    void OnTaskCtrlDataEvent(CTaskCtrlData &aData, 
                                    const unsigned int aDataSequence,
                                    CTaskCtrlClient &aTaskCtrlClient,
                                    void * aUserPtr) {
        dPrint(ODTEST,"Hey, we got an TaskCtrlClientEvent no %d from %p!", aDataSequence, &aTaskCtrlClient);
        TTaskCtrlStatusEvent tcEvent;
        
        //--------Check data okness---------------------
        if (aData.GetTaskCtrlStatusEvent()!=NULL) {            
            tcEvent.taskID = aData.GetTaskCtrlStatusEvent()->taskID;
            tcEvent.taskState = aData.GetTaskCtrlStatusEvent()->taskState;
            tcEvent.ETC_ms = aData.GetTaskCtrlStatusEvent()->ETC_ms;
            tcEvent.percentComplete = aData.GetTaskCtrlStatusEvent()->percentComplete;
            tcEvent.Print(1);
        }
    }
};

static CTaskCtrlUser taskctrluser;
//*****************************************************************************

static int ExecuteExampleClient(gimi::GIMI &g)
{
  // TaskCtrl client instance
  // Traditional form, where the GIMI is given as preconnected pointer
  // to the TaskCtrlClient instance.
  CTaskCtrlClient dc(&g, 0);

  // TaskCtrl data instance
  CTaskCtrlData dd;
  dd.CreateInternalBinBag();
  CTaskCtrlData dataOut;
  dataOut.CreateInternalBinBag();
  bool r;

  // Variable for storing thread id.
  //ownThreadHandle dummyWatchThread;

  // Init random generator.
  srandom(time(NULL));

  
  /*// Execute service discovery for TaskCtrl.
  gimi::t_serviceList serviceArray;
#warning Rename to GetTaskCtrlServiceArray
  assert ( dc.GetTaskCtrlServices(serviceArray, 3000) == true );
  
  // Execute TaskInfo query for TaskCtrl services.
  TTaskCtrlServiceEntryArray serviceInfoArray;
  assert ( dc.GetServiceInfoArray(serviceInfoArray,
                                  serviceArray,
                                  3000) == true );
  // Print
  for (EACH_IN_i(serviceInfoArray)) {
    i->Print(ODTEST);
  }
  
  // Execute filter.
  TTaskCtrlServiceEntryArray taskInfoArray;
  TTaskCtrlServiceEntryArray microTaskInfoArray;
  
  // Tasks
  dc.FilterServiceInfoArray(taskInfoArray,
                            serviceInfoArray,
                            KServiceTypeTask);


  // Microtasks
  dc.FilterServiceInfoArray(taskInfoArray,
                            serviceInfoArray,
                            KServiceTypeMicroTask);
  
  dPrint(ODTEST,"Complete");
  //exit(1);

    */


  // Assign default target.
  if (datasource.size()) {
    dc.SetDefaultTarget(datasource);

  } else {
    // GIMI is Open(), so we can execute this.
    MaCICtrl::SMaCISL sl(datasourceMaCISL);
    if (sl.IsValidFQMaCISL()) {
      dc.SetDefaultTarget(sl, 10000);
    }
    
  } 
  
  ///////////////////////////////////////////////////////
  ////////////Set TaskCtrl client callback///////////////
  /////////////////////////////////////////////////////// 
   dc.SetTaskCtrlClientCallback(&taskctrluser);  
  
  // Open.
  if (dc.Open() == KMaCIOK) {
    dPrint(ODINFO,"Succesfully Open():ed TaskCtrlClient, BWT, you have connected to service: '%s'",
    dc.GetDefaultTargetMaCISL().ToMaCISLString().c_str());
    //dummyWatchThread = ownThread_Create((void*)dummyWatch, &dc);
    unsigned int major =1;
    int minor0 = 0;
    unsigned int sequence = 0;
    while(run) {
  //////////////////////////////////////////////////////////
  ///////// Encode /////////////////////////////////////////
  //////////////////////////////////////////////////////////
      dd.Reset();
      dataOut.Reset();
      dPrint(ODINFO,"\nEncoding...\n");
      // Do Encoding 
           
      dPrint(ODINFO,"Encode: Timestamp(1,2) ... ");
      r = dd.SetTimestamp(MaCI::Common::TTimestamp(1, 2));
      assert(r == true);
      dPrint(ODINFO,"OK.\n");
      
      dPrint(ODINFO,"Encode: TCommand(KCommandAddTask, 0, 21, 1001) ... ");
      
      TTaskCtrlTaskID taskID(major,0,0,0,0);
      r = dd.SetCommand(TCommand(KCommandAddTask, KCommandFlagDefault, taskID, 1001));
      assert(r == true);
      dPrint(ODINFO,"OK.\n");
      
      dPrint(ODINFO,"Encode: TaskCtrlContractedTask; data='<foo>diibadaabadaa</foo>'");
      
      
      for (int i = 0; i<4; i++) {          
          TTaskCtrlContract contract(TTaskCtrlTaskID(major,minor0,0,0,0), 1144.0, 120, 0);
          
          std::string diiba= "<foo>diibadaabadaa</foo>";
          uint8_t *ptr = NULL;
          unsigned int bytes = 0;
          // Create dynamic container from xmlString
          TTaskCtrlXML *tcxml = TTaskCtrlXML::CreateTextElement(&ptr, bytes, diiba);  
          dd.AddTaskCtrlContract(contract);
          dd.AddTaskCtrlXML(*tcxml);   
          //TTaskCtrlContractedTask contractedTask(contract, *tcxml);       
          //r = dd.AddTaskCtrlContractedTask(contractedTask);
          assert(r == true);
          minor0++;
      }
      
      dd.Print(0);
      
      if(dc.GetDataBySynchronousCall(dd, dataOut, sequence, 15000)) {
          dPrint(ODINFO,"Got Reply");
      }
      else {
           dPrint(ODINFO,"No Reply");
      }
      sequence++;
      // Wait for a "moment".
      const unsigned int sleepTime = 1000 + random() % 5000;
      dPrint(1,"Sleeping for %u milliseconds...", sleepTime);
      ownSleep_ms(sleepTime);
    }
  } else {
    dPrint(1,"Failed to Open() TaskCtrlClient.");

  }
  return 0;
}


//*****************************************************************************
static int ExecuteInteractiveExampleClient(gimi::GIMI &g)
{
  // TaskCtrl client instance
  // Traditional form, where the GIMI is given as preconnected pointer
  // to the TaskCtrlClient instance.
  CTaskCtrlClient dc(&g, 0);
  
  // Assign default target.
  if (datasource.size()) {
    dc.SetDefaultTarget(datasource);

  } else {
    // GIMI is Open(), so we can execute this.
    MaCICtrl::SMaCISL sl(datasourceMaCISL);
    if (sl.IsValidFQMaCISL()) {
      dc.SetDefaultTarget(sl, 10000);
    }
    
  } 
  // dc.SetTaskCtrlClientCallback(&taskctrluser);  
  
  // Open.
  if (dc.Open() == KMaCIOK) {
    dPrint(ODINFO,"Succesfully Open():ed TaskCtrlClient, BWT, you have connected to service: '%s'",
    dc.GetDefaultTargetMaCISL().ToMaCISLString().c_str());
    
  
    // Initialize Curses (After this point, don't use printf family calls!)
    initscr(); 
    cbreak(); 
    //noecho();
    nonl();
    intrflush(stdscr, FALSE);
    keypad(stdscr, TRUE);
    scrollok(stdscr, TRUE);
    //nodelay(stdscr, TRUE);
    //halfdelay(10);
    
    // After this point, we don't want dPrint to print to Screen, so we disable it.
    debugSetPrintLevel(0);
    debugSetLogLevel(5);
    
    clear();
    printw("Welcome to TaskCtrlClient test program.\n\n");
    unsigned int sequence = 0; //Sequence for taskctrlevent
    do {
      int r;
      int value;
      printw("\nSelect TaskCtrl Query:\n");
      printw("S = Start TaskCtrl\n");
      printw("O = Stop TaskCtrl\n");
      printw("P = Pause TaskCtrl\n");
      printw("a = Add Task:\n");
      printw("A = Add Task to library\n");
      printw("r = Remove Task:\n");
      printw("R = Remove task from library\n");
      printw("i = Init Task:\n");
      printw("s = Start Task:\n");
      printw("o = Stop Task:\n");
      printw("p = Pause Task:\n");
      printw("c = Continue Task:\n");
      printw("g = Get Task library:\n");
      printw("t = Get Task table:\n");
      printw("e = Get task state:\n");
      printw("E = Wait for TaskCtrl event(5000ms)\n");
      printw("q = QUIT\n");

      printw("?\n");
      value = getch();
      clear(); // After input, clear the screen. Not after processing!
      switch(value){

      case 'S':{
        printw("Starting TASKCTRL\n");
        dc.StartTaskCtrl();
        break;
      }

      case 'O':{        
        printw("Stopping TASKCTRL");
        dc.StopTaskCtrl();
        break;

      }

      case 'P':{
        printw("Pausing TASKCTRL");
        dc.PauseTaskCtrl();
        break;
      }
      case 'a':{
        unsigned int timeout_ms = 5000;
        printw("Enter Task ID: <typeID0 typeID1 typeID2 typeID3 typeID4 typeID5 typeID6>");
        int typeID0,typeID1,typeID2,typeID3,typeID4,typeID5,typeID6;
        r = scanw("%d %d %d %d %d %d %d",&typeID0,&typeID1,&typeID2,&typeID3,&typeID4,&typeID5,&typeID6);
        if(r >=7){
          printw("Generating xml...");
          std::stringstream out;
          //JUST AN EXAMPLE... DO NOT DO LIKE THIS :)
          out << "<task> foobaar "<<typeID0<<" </task>\n<Id> "<<typeID1 <<"."<< typeID2 <<"."<< typeID3 <<"."<< typeID4 << "."<< typeID5<<"."<<typeID6<<"</Id>"<< std::endl;
          
          std::string s =  out.str();
          printw("\n %s", s.c_str());
          TTaskCtrlTaskID id(typeID0,typeID1,typeID2,typeID3,typeID4,typeID5,typeID6);
          printw("id= %d %d %d %d %d %d %d\n",
                 typeID0,typeID1,typeID2,typeID3,typeID4,typeID5,typeID6);
          
          if(dc.AddTask(id, s,timeout_ms)){
            printw("%s",id.GetString().c_str());

          }else{
            printw("Failed to add task");
          }
        }else{
          printw("Not enough arguments... \n");
        }

        break;
      }

      case 'A':{
        
        printw("Enter Task ID: <typeID0 typeID1 typeID2 typeID3 typeID4 typeID5 typeID6>");
        int typeID0,typeID1,typeID2,typeID3,typeID4,typeID5,typeID6;
        unsigned int timeout_ms = 5000;
        r = scanw("%d %d %d %d %d %d %d",&typeID0,&typeID1,&typeID2,&typeID3,&typeID4,&typeID5,&typeID6);
        if(r >=7){
          printw("Generating xml...");
          
          std::stringstream out;
          //JUST AN EXAMPLE... DO NOT DO LIKE THIS :)
          out << "<task> foobaar "<<typeID0<<" </task>\n<Id> "<<typeID1 <<"."<< typeID2 <<"."<< typeID3 <<"."<< typeID4 << "."<< typeID5<<"."<<typeID6<<"</Id>"<< std::endl;
          std::string s =  out.str();
          printw("\n %s", s.c_str());
          TTaskCtrlTaskID id(typeID0,typeID1,typeID2,typeID3,typeID4,typeID5,typeID6);
          std::string errorString="";
          if(dc.AddTaskToLibrary(id, s,timeout_ms,errorString)){
            printw("Added Task succesfully, got for task ID: typeID0 = %u typeID1 = %u typeID2 = %u typeID3 = %u typeID4 = %u typeID5 = %u typeID6 = %u host = %u owner = %u taskID = %u ",
                   id.typeID0,
                   id.typeID1,
                   id.typeID2,
                   id.typeID3,
                   id.typeID4,
                   id.typeID5,
                   id.typeID6,
                   id.host,
                   id.owner,
                   id.taskID);

                   

          }else{
            printw("Failed to add task");
            printw("Error string '%s'", errorString.c_str());
          }
          
        }else{
          printw("Not enough arguments... \n");
        }
        break;
      }
      case 'r':{
        printw("Enter Task ID to remove from TABLE: <taskID>");
        int taskID;
        r = scanw("%d",&taskID);
        if(r >=1){
          printw("Removing task from TABLE with id %d...",
                 taskID);
          if(dc.RemoveTask(taskID)){
            printw("SUCESS\n");
          }else{
            printw("FAILED\n");
          }
        }else{
          printw("Not enough id numbers.. \n");
        }

        break;
      }

      case 'R':{

        printw("Enter Task ID to remove from LIBRARY: <typeID0 typeID1 typeID2 typeID3 typeID4 typeID5 typeID6>");
        int typeID0,typeID1,typeID2,typeID3,typeID4,typeID5,typeID6;

        r = scanw("%d %d %d %d %d %d %d",&typeID0,&typeID1,&typeID2,&typeID3,&typeID4,&typeID5,&typeID6);
        if(r >=7){
          printw("Removing Task from library with task ID: typeID0 = %u typeID1 = %u typeID2 = %u typeID3 = %u typeID4 = %u typeID5 = %u typeID6 = %u host = %u owner = %u taskID = %u ",
                 typeID0,
                 typeID1,
                 typeID2,
                 typeID3,
                 typeID4,
                 typeID5,
                 typeID6);
          if(dc.RemoveTaskFromLibrary(TTaskCtrlTaskID(typeID0,typeID1,typeID2,typeID3,typeID4,typeID5,typeID6))){
            printw("SUCESS\n");
          }else{
            printw("FAILED\n");
          }
        }else{
          printw("Not enough id numbers.. \n");
        }
        break;
      }
      case 'i':{
        printw("Enter Task ID to init: <taskID>");
        int id;
        r = scanw("%d",&id);
        if(r >=1){
          printw("Initializing task from TABLE with id %d...",
                 id);
          if(dc.InitTask(id)){
          }else{
            printw("Failed\n");
          }
          break;
        }else{
          printw("Not enough arguments...");
        }
      }
      case 's':{
        printw("Enter Task ID to start: <taskID>");
        int id;
        r = scanw("%d",&id);
        if(r >=1){
          printw("Starting task from TABLE with id %d...",
                 id);
          if(dc.StartTask(id)){
          }else{
            printw("Failed\n");
          }
        }else{
          printw("Not enough arguments...");
        }

        break;
      }
      case 'o':{
        printw("Enter Task ID to STOP: <taskID>");
        int id;
        r = scanw("%d",&id);

        if(r >=1){
          printw("Stopping task from TABLE with id %d...",
                 id);
          if(dc.StopTask(id)){
          }else{
            printw("Failed");
          }
        }else{
          printw("Not enough arguments...  \n");
        }

        break;
      }
      case 'p':{
        printw("Enter Task ID to PAUSE: <taskID>");
        int id;
        r = scanw("%d",&id);

        if(r >=1){

          printw("Pausing task from TABLE with id %d...",
                 id);
          if(dc.PauseTask(id)){
          }else{
            printw("Failed\n");
          }
        }else{
          printw("Not enough arguments... \n");
        }
        break;
      }

      case 'c':{
        printw("Enter Task ID to CONTINUE: <taskID>");
        int id;
        r = scanw("%d",&id);
        
        if(r >=1){
        
          printw("Continuing task from TABLE with id %d...",
                 id);
          if(dc.ContinueTask(id)){
          }else{
            printw("Failed\n");
          }
        }else{
          printw("Not enough arguments... \n");
        }
        break;
      }

      case 'g':{
        std::vector<std::string> tasksXML;

        TTaskCtrlTaskStateArray taskStates;
        unsigned int timeout = 5000;
        if(dc.GetTaskLibrary(taskStates,tasksXML,timeout)){
          if(taskStates.size() == tasksXML.size()){
            printw("Got task library, it contains %d tasks. Printing them:\n",
                   taskStates.size());
            for(unsigned int i = 0; i< taskStates.size(); i++){
              printw("------------------------------------------------\n");
              printw("Task ID: %d %d %d %d %d %d %d %d %d %d\n",
                     taskStates[i].taskID.typeID0,
                     taskStates[i].taskID.typeID1,
                     taskStates[i].taskID.typeID2,
                     taskStates[i].taskID.typeID3,
                     taskStates[i].taskID.typeID4,
                     taskStates[i].taskID.typeID5,
                     taskStates[i].taskID.typeID6,
                     taskStates[i].taskID.host,
                     taskStates[i].taskID.owner,
                     taskStates[i].taskID.taskID);
              printw("TASK XML:\n%s\n",
                     tasksXML[i].c_str());
              printw("------------------------------------------------\n");
            }
          }else{
            printw("Something is wrong. Arrays sizes are different???");
          }
        }else{
          printw("Failed\n");
        }
        
        break;
      }

      case 't':{
        std::vector<std::string> tasksXML;
        TTaskCtrlTaskStateArray taskStates;
        unsigned int timeout = 5000;
        if(dc.GetTaskTable(taskStates,tasksXML,timeout)){
          if(taskStates.size() == tasksXML.size()){
            printw("Got %u tasks:\n",taskStates.size());
            for(unsigned int i = 0; i <taskStates.size(); i++){
              printw("------------------------------------------------\n");
              printw("%u.",i);
              printw("TTaskID:: typeID0 = %u typeID1 = %u typeID2 = %u typeID3 = %u typeID4 = %u typeID5 = %u typeID6 = %u host = %u owner = %u taskID = %u ",
                     taskStates[i].taskID.typeID0,
                     taskStates[i].taskID.typeID1,
                     taskStates[i].taskID.typeID2,
                     taskStates[i].taskID.typeID3,
                     taskStates[i].taskID.typeID4,
                     taskStates[i].taskID.typeID5,
                     taskStates[i].taskID.typeID6,
                     taskStates[i].taskID.host,
                     taskStates[i].taskID.owner,
                     taskStates[i].taskID.taskID);
              
              printw("Task state %d, ETC %u, percentComplete %f\n",
                     taskStates[i].taskState,
                     taskStates[i].ETC_ms,
                     taskStates[i].percentComplete);

              printw("TASK XML:\n%s",
                     tasksXML[i].c_str());
              printw("------------------------------------------------\n");
                     
              
            }

          }else{
            printw("Something is wrong. Arrays sizes are different???");
          }
        }else{
          printw("Failed\n");
        }
        break;
      }
      case 'e':{

        TTaskCtrlTaskState state;

        printw("Enter Task ID: <taskID>");
        int id;
        r = scanw("%d",&id);
        if(r >=1){
         
          unsigned int timeout = 5000;
          if(dc.GetTaskState(id,state,timeout)){
            printw("TTaskID:: typeID0 = %u typeID1 = %u typeID2 = %u typeID3 = %u typeID4 = %u typeID5 = %u typeID6 = %u host = %u owner = %u taskID = %u ",
                   state.taskID.typeID0,
                   state.taskID.typeID1,
                   state.taskID.typeID2,
                   state.taskID.typeID3,
                   state.taskID.typeID4,
                   state.taskID.typeID5,
                   state.taskID.typeID6,
                   state.taskID.host,
                   state.taskID.owner,
                   state.taskID.taskID);
              


            printw("Got Task State: taskState %d\n", state.taskState);
            printw("Got Task State: ETC_ms %u\n", state.ETC_ms);
            printw("Got Task State: percentComplete %f\n", state.percentComplete);
            
            
          }else{
            
            printw("Failed to get task state\n");
          }
        }else{
          printw("Not enough arguments!\n");
        }
        break;
        
      }

      case 'E':{
        printw("Waiting for taskctrlEvent..");
        CTaskCtrlData data;
        if(dc.WaitForTaskCtrlEvent(data,&sequence,5000)){
          printw("Got Data!\n");
          const TCommand *cmd = data.GetCommand();
          if(cmd){
            printw("Got command %d",cmd->cmd);
          }else{
            //Got an event
            const TTaskCtrlStatusEvent *event = data.GetTaskCtrlStatusEvent();
            if(event){
              printw("Got taskctrl status event (Sequence n.%u):\n",
                     sequence);

              printw("TTaskID:: typeID0 = %u typeID1 = %u typeID2 = %u typeID3 = %u typeID4 = %u typeID5 = %u typeID6 = %u host = %u owner = %u taskID = %u ",
                   event->taskID.typeID0,
                   event->taskID.typeID1,
                   event->taskID.typeID2,
                   event->taskID.typeID3,
                   event->taskID.typeID4,
                   event->taskID.typeID5,
                   event->taskID.typeID6,
                   event->taskID. host,
                   event->taskID.owner,
                   event->taskID.taskID);
              printw("taskState %d\n", event->taskState);
              printw("ETC_ms %u\n", event->ETC_ms);
              printw("percentComplete %f\n", event->percentComplete);
              
            }else{
              printw("No TTaskctrlstatusEvent container in messsage!!??\n");
            }
          }
        }else{
          printw("Timeout!\n");
        }
        break;
      }
      case 'q':
        
        run = false;
        printw("\nBYE BYE!.\n\n");
      
        break;
        
      default:
        clear();
        printw("\nUnknown command.\n\n");
        continue;
        break;
      }
      
    } while(run);
  }else{
    dPrint(1,"Failed to Open() TaskCtrlClient.");

  }
  
  // Close curses.
  endwin();
 
  return 0;
}
int main(int argc, char *argv[]) 
{
  // GIMnet parameters
  std::string gimnetAP = "asrobo.hut.fi";
  int gimnetAPPort = 40002;
  std::string gimnetName;

  bool interactive = false;
  // setup signal handling
  InitSignalHandler();

  // Objects
  gimi::GIMI g;

  // Init Debug lib
  debugInit();
  debugSetGlobalDebugLvl(4);
  const std::string logfile = std::string(argv[0]) + ".log";
  debugSetLogFilename(logfile.c_str());
  debugAddMode(DEBUG_MODE_IMMEDIATE_FLUSH);
  // Greet
  fprintf(stderr,
	  "\n%s - $Revision: 1.9 $\n", argv[0]);

  /////////////////////////////////////////////////////////////////////////////
  // Parse parameters - Remember: ** DO NOT MODIFY OR DELETE ANY OF THIS **
  // _Add_ anything as you wish.
  ///////////////////////////////////////////////////////////////////////////// 
  bool parse = true;
  while(parse) {
    int c;
    c = getopt(argc, argv, "n:u:p:s:S:ihqv");
    switch(c) {

      /////////////////////////////////
      ////// Application specific /////
      /////////////////////////////////

    case 's':
      datasource = optarg;
      dPrint(3,"Using DataSource '%s'", optarg);
      break;

    case 'S':
      datasourceMaCISL = optarg;
      dPrint(3,"Using DataSource MaCISL '%s'", optarg);
      break;

    case 'i':
      interactive = true;
      dPrint(1,"Using iteractive mode");
      break;
      /////////////////////////////////////////////////////////////////////////
      /// Add here anything you need.
      /////////////////////////////////////////////////////////////////////////

      /////////////////////////////////
      ///// MaCI/GIMnet parameters ////
      /////////////////////////////////
    case 'n':
      gimnetName = optarg;
      dPrint(3,"Using GIMnet Name '%s'", optarg);
      break;

    case 'u':
      gimnetAP = optarg;
      dPrint(3,"Using GIMnetAP address '%s'", optarg);
      break;

    case 'p':
      gimnetAPPort = atoi(optarg);
      dPrint(3,"Using GIMnetAP port '%d'", gimnetAPPort);
      break;

      //////////////////////////////////
      //// GENERIC:                 ////
      //////////////////////////////////
    case 'v':
      // Increase only if not previously set to 0 (by 'quiet')
      if (verbose > 0)
	debugSetGlobalDebugLvl(++verbose);
      break;
      
    case 'q':
      verbose = 0;
      debugSetGlobalDebugLvl(0);
      break;
      
    case 'h':
    case '?':
      showUsage();
      exit(1);
      break;
      
    case -1:
      parse = false;
      break;
    }
  }
  
  /////////////////////////////////////////////////////////////////////////////
  // Execute connection to GIMnet.
  /////////////////////////////////////////////////////////////////////////////
  int r;
  if ( (r = g.connectToHubEx(gimnetAP, gimnetAPPort, gimnetName) ) != GIMI_OK) {
    dPrint(1,"Failed to connect to GIMnet AccessPoint '%s:%d' with name '%s': '%s'",
	   gimnetAP.c_str(), 
	   gimnetAPPort, 
	   gimnetName.size()?gimnetName.c_str():"<anonymous>",
	   gimi::getGimiErrorString(r).c_str());
    
  } else {
    dPrint(2,"Succesfully connected to GIMnet at AccessPoint '%s:%d' with name '%s': '%s'",
	   gimnetAP.c_str(), 
	   gimnetAPPort, 
	   gimnetName.size()?gimnetName.c_str():"<anonymous>",
	   gimi::getGimiErrorString(r).c_str());
    
    // GIMnet connection OK, now execute module.
    dPrint(ODINFO,"Connected, executing client");
    if(!interactive){
      r = ExecuteExampleClient(g);
    }else{
      r = ExecuteInteractiveExampleClient(g);
    }
  }

  return 0;
}
//*****************************************************************************
//*****************************************************************************
/******************************************************************************
 * 
 * $Log: not supported by cvs2svn $
 * Revision 1.8  2009-09-18 10:19:23  mmatusia
 * added example line
 *
 * Revision 1.7  2009-09-18 09:56:45  mmatusia
 * works.
 *
 * Revision 1.6  2009-09-18 09:29:54  mmatusia
 * Callback function for handling of events.
 *
 * Revision 1.5  2009-08-31 13:24:00  mmatusia
 * Added data generation and synchronous comms.
 *
 * Revision 1.4  2009-05-14 11:06:17  amaula
 * More work on TaskCtrl interface.
 *
 * Revision 1.3  2009-05-13 07:18:15  amaula
 * Doxygens file tag parameter removed, as no parameter means 'document this file'
 *
 * Revision 1.2  2009-05-06 07:57:05  amaula
 * Some work  for the TaskCtrl interface
 *
 * Revision 1.1  2009-04-29 10:27:25  amaula
 * Baseline added.
 *
 *
 *****************************************************************************/
//*****************************************************************************
//*****************************************************************************


